package com.yboot.module.system.auth.service.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.yboot.module.business.common.cache.CaptchaCache;
import com.yboot.module.system.auth.model.dto.LoginDto;
import com.yboot.module.system.auth.model.vo.AccessTokenVo;
import com.yboot.module.system.auth.service.IAuthService;
import com.yboot.module.system.model.entity.SysClientEntity;
import com.yboot.module.system.model.vo.SysUserVo;
import com.yboot.module.system.service.*;
import com.yboot.starter.cache.middle.RedisUtil;
import com.yboot.starter.common.core.constant.DisEnableStatusEnum;
import com.yboot.starter.common.core.exception.BusinessException;
import com.yboot.starter.common.core.userdetails.LoginUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 认证
 *
 * @author ycs
 * @date 2025/8/30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements IAuthService {

    private final ISysUserService sysUserService;
    private final ISysClientService sysClientService;
    private final ISysRoleService sysRoleService;
    private final ISysMenuService sysMenuService;
    private final RedisUtil redisUtil;

    @Override
    public AccessTokenVo login(LoginDto loginDto) {
        SysClientEntity client = sysClientService.getByClientId(loginDto.getClientId());
        Assert.isFalse(client == null, "客户端不存在");
        Assert.isFalse(DisEnableStatusEnum.DISABLE.getCode().equals(client.getStatus()), "客户端已禁用");
        Assert.isFalse(!client.getAuthType().contains(loginDto.getAuthType()), "该客户端暂未授权认证" + client.getAuthType());
        if (client.getAuthType().contains("code")) {
            validateCaptcha(loginDto.getCode(), loginDto.getUuid());
        }
        LoginUser loginUser = loadByUsername(loginDto.getUsername());
        Assert.isFalse(loginUser.isAccountLocked(), "账号已锁定");
        //密码校验
        if (!loginDto.getPassword().equals(loginUser.getPassword())) {
            throw new BusinessException("密码错误");
        }
        StpUtil.login(loginUser.getId(), client.getClientType());
        StpUtil.getSession().set(SaSession.USER, loginUser);
        String token = StpUtil.getTokenValueByLoginId(loginUser.getId());
        return new AccessTokenVo(token);
    }

    /**
     * 校验验证码
     *
     * @param code     验证码
     * @param uuid     唯一标识
     * @return 结果
     */
    public void validateCaptcha(String code, String uuid) {
        String verifyKey = CaptchaCache.CAPTCHA_CODE_KEY + StrUtil.blankToDefault(uuid, "");
        String captcha = redisUtil.get(verifyKey);
        if (captcha == null) {
            throw new BusinessException("验证码已失效");
        }
        redisUtil.del(verifyKey);
        if (!code.equalsIgnoreCase(captcha)) {
            throw new BusinessException("验证码错误");
        }
    }

    @Override
    public LoginUser loadByUsername(String username) {
        SysUserVo sysUserVo = sysUserService.getByUsername(username);
        Assert.isFalse(sysUserVo == null, "用户不存在");
        LoginUser loginUser = new LoginUser();
        BeanUtil.copyProperties(sysUserVo, loginUser);
        loginUser.setAccountLocked(DisEnableStatusEnum.DISABLE.getCode().equals(sysUserVo.getStatus()));
        //角色
        loginUser.setRoleSet(sysRoleService.getRoleSet(sysUserVo.getId()));
        //数据权限
        if (loginUser.getRoleSet().contains("admin")) {
            loginUser.setPermissionSet(new HashSet<>(Arrays.asList("*:*:*")));
        } else {
            loginUser.setPermissionSet(sysMenuService.getPermissionSet(sysUserVo.getId()));
        }
        return loginUser;
    }
}
